package com.example.maze.swing;

import com.example.maze.model.Cell;
import com.example.maze.model.Coordinate;
import com.example.maze.model.Maze;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.swing.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Swing动画控制器
 * 
 * @author maze-demo
 */
public class SwingAnimationController {
    private static final Logger logger = LoggerFactory.getLogger(SwingAnimationController.class);
    
    private MazePanel mazePanel;
    private AnimatedMazeSolver currentSolver;
    private ExecutorService executorService;
    private boolean isAnimating = false;
    private boolean isPaused = false;
    private volatile boolean cancelled = false;
    
    // 动画状态监听器
    private Consumer<AnimationState> stateListener;
    private Consumer<SolverStep> stepListener;
    private Consumer<AnimatedSolverResult> resultListener;
    
    public SwingAnimationController(MazePanel mazePanel) {
        this.mazePanel = mazePanel;
        this.executorService = Executors.newSingleThreadExecutor();
    }
    
    /**
     * 动画状态枚举
     */
    public enum AnimationState {
        IDLE,           // 空闲
        RUNNING,        // 运行中
        PAUSED,         // 暂停
        COMPLETED,      // 完成
        CANCELLED       // 取消
    }
    
    /**
     * 开始寻路动画
     */
    public void startAnimation(Maze maze, AnimatedMazeSolver solver) {
        if (isAnimating) {
            logger.warn("动画正在运行中，无法启动新动画");
            return;
        }
        
        this.currentSolver = solver;
        this.isAnimating = true;
        this.isPaused = false;
        this.cancelled = false;
        
        // 重置迷宫显示
        mazePanel.setMaze(maze);
        mazePanel.resetDisplay();
        
        notifyStateChange(AnimationState.RUNNING);
        
        // 创建异步任务
        executorService.execute(new Runnable() {
            @Override
            public void run() {
                logger.info("开始执行寻路动画: {}", solver.getName());
                
                try {
                    AnimatedSolverResult result = solver.solveWithAnimation(maze, new Consumer<SolverStep>() {
                        @Override
                        public void accept(SolverStep step) {
                            // 在EDT中处理步骤
                            SwingUtilities.invokeLater(new Runnable() {
                                @Override
                                public void run() {
                                    if (!cancelled && !isPaused) {
                                        handleStep(step);
                                    }
                                }
                            });
                        }
                    });
                    
                    // 处理完成事件
                    SwingUtilities.invokeLater(new Runnable() {
                        @Override
                        public void run() {
                            isAnimating = false;
                            
                            if (cancelled) {
                                logger.info("寻路动画被取消");
                                notifyStateChange(AnimationState.CANCELLED);
                            } else {
                                logger.info("寻路动画完成: {}", result);
                                notifyStateChange(AnimationState.COMPLETED);
                                notifyResult(result);
                            }
                        }
                    });
                } catch (Exception e) {
                    SwingUtilities.invokeLater(new Runnable() {
                        @Override
                        public void run() {
                            isAnimating = false;
                            logger.error("寻路动画执行失败", e);
                            notifyStateChange(AnimationState.CANCELLED);
                        }
                    });
                }
            }
        });
    }
    
    /**
     * 暂停动画
     */
    public void pauseAnimation() {
        if (!isAnimating || isPaused) {
            return;
        }
        
        isPaused = true;
        notifyStateChange(AnimationState.PAUSED);
        logger.info("寻路动画已暂停");
    }
    
    /**
     * 继续动画
     */
    public void resumeAnimation() {
        if (!isAnimating || !isPaused) {
            return;
        }
        
        isPaused = false;
        notifyStateChange(AnimationState.RUNNING);
        logger.info("寻路动画已继续");
    }
    
    /**
     * 停止动画
     */
    public void stopAnimation() {
        if (!isAnimating) {
            return;
        }
        
        cancelled = true;
        
        isAnimating = false;
        isPaused = false;
        notifyStateChange(AnimationState.CANCELLED);
        logger.info("寻路动画已停止");
    }
    
    /**
     * 处理寻路步骤
     */
    private void handleStep(SolverStep step) {
        // 等待暂停状态结束
        while (isPaused && !cancelled) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                return;
            }
        }
        
        if (cancelled) {
            return;
        }
        
        logger.debug("处理动画步骤: {}", step);
        
        switch (step.getType()) {
            case VISIT:
                handleVisitStep(step);
                break;
            case BACKTRACK:
                handleBacktrackStep(step);
                break;
            case SOLUTION:
                handleSolutionStep(step);
                break;
            case START:
            case END:
                // 开始和结束步骤不需要特殊处理
                break;
        }
        
        // 通知步骤监听器
        notifyStep(step);
    }
    
    /**
     * 处理访问步骤
     */
    private void handleVisitStep(SolverStep step) {
        Coordinate coord = step.getCoordinate();
        if (coord != null) {
            // 更新迷宫中的单元格状态
            Cell cell = mazePanel.getMaze().getCell(coord);
            if (cell.getType() == Cell.Type.PATH) {
                cell.setType(Cell.Type.VISITED);
            }
            
            // 更新显示并高亮当前单元格
            mazePanel.updateCell(coord);
            mazePanel.highlightCurrentCell(coord);
        }
    }
    
    /**
     * 处理回溯步骤
     */
    private void handleBacktrackStep(SolverStep step) {
        Coordinate coord = step.getCoordinate();
        if (coord != null) {
            mazePanel.highlightCurrentCell(coord);
        }
    }
    
    /**
     * 处理解路径步骤
     */
    private void handleSolutionStep(SolverStep step) {
        Coordinate coord = step.getCoordinate();
        if (coord != null) {
            // 更新迷宫中的单元格状态
            Cell cell = mazePanel.getMaze().getCell(coord);
            if (cell.getType() != Cell.Type.START && cell.getType() != Cell.Type.END) {
                cell.setType(Cell.Type.SOLUTION);
            }
            
            // 更新显示
            mazePanel.updateCell(coord);
            mazePanel.highlightCurrentCell(coord);
        }
    }
    
    /**
     * 设置动画速度
     */
    public void setAnimationSpeed(int delayMs) {
        if (currentSolver != null) {
            currentSolver.setAnimationDelay(delayMs);
        }
    }
    
    /**
     * 获取当前动画速度
     */
    public int getAnimationSpeed() {
        return currentSolver != null ? currentSolver.getAnimationDelay() : 100;
    }
    
    // 监听器设置方法
    public void setStateListener(Consumer<AnimationState> listener) {
        this.stateListener = listener;
    }
    
    public void setStepListener(Consumer<SolverStep> listener) {
        this.stepListener = listener;
    }
    
    public void setResultListener(Consumer<AnimatedSolverResult> listener) {
        this.resultListener = listener;
    }
    
    // 通知方法
    private void notifyStateChange(AnimationState state) {
        if (stateListener != null) {
            stateListener.accept(state);
        }
    }
    
    private void notifyStep(SolverStep step) {
        if (stepListener != null) {
            stepListener.accept(step);
        }
    }
    
    private void notifyResult(AnimatedSolverResult result) {
        if (resultListener != null) {
            resultListener.accept(result);
        }
    }
    
    // 状态查询方法
    public boolean isAnimating() {
        return isAnimating;
    }
    
    public boolean isPaused() {
        return isPaused;
    }
    
    public AnimatedMazeSolver getCurrentSolver() {
        return currentSolver;
    }
    
    /**
     * 清理资源
     */
    public void shutdown() {
        if (executorService != null) {
            executorService.shutdown();
        }
    }
}